/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Máté
 */

// vezetéket megvalósító osztály
public class Wire implements IComposite {

    // a vezeték állapotát fejezi ki
    private Boolean isHighLevel;
    // számláló a stabilitásvizsgálat végett
    private Integer counter;
    // kijelző referenciája
    private Display display;
    private Oscilloscope oscilloscope;
    // vezetékre csatlakozó kapuk
    private List<Gate> outputs;

    // inicializáció
    public Wire() {
        this.display = null;
        this.oscilloscope = null;
        this.isHighLevel = false;
        this.counter = 0;
        this.outputs = new ArrayList<Gate>();
    }

    // lista bővítésére szolgáló metódus
    public void addGate(Gate gate) {
        this.outputs.add(gate);
    }

    public Display getDisplay() {
        return display;
    }

    public Oscilloscope getOscilloscope() {
        return oscilloscope;
    }

    public List<Gate> getOutputs() {
        return outputs;
    }

    // kijelző beállítása
    public void setDisplay(Display display) {
        this.display = display;
    }

    public void setOscilloscope(Oscilloscope oscilloscope) {
        this.oscilloscope = oscilloscope;
        ScopeWatch.addOscilloscope(this.oscilloscope);
    }

    public Boolean isHighLevel() {
        return isHighLevel;
    }

    // számlálók léptetését és nullázását végző metódus
    public void count(Boolean isReseted) throws Exception {
        if (isReseted) {
            this.counter = 0;
            for (Gate output : this.outputs) {
                // ha reset volt, akkor Dejavu bitet nullázzuk
                output.setDejavu(false);
            }
        } else {
            this.counter++;

            if (this.counter == 100) {
                // a hálózat oszcillál, hibát dobunk
                throw new Exception("Error: Unstable circuit!");
            }
        }
    }

    public void update(Boolean value) {

        try {
            // megjegyezzük, hogy a Wire régi állpota más-e, mint az új
            Boolean changed = this.isHighLevel != value;

            this.isHighLevel = value;

            // ha igen, növeljük a számlálót
            if (changed) {
                this.count(false);
            }

            if (this.display != null) {
                // kijelezzük az átvitt értéket
                this.display.switchLight(value);
            }

            if(this.oscilloscope != null){
                this.oscilloscope.read(value);
            }

            // visszacsatolás vizsgálata:
            // ha a vezeték régi állapota nem egyezik meg az újjal,
            // vagy a legutóbbi reset óta most először vizsgáljuk,
            // akkor kiértélelődnek a rá kötött kapuk
            for (Gate output : this.outputs) {
                if (output.isDejavu() == false || changed) {
                    output.setDejavu(true);
                    output.gateFunc();
                }

            }

        } // instabil hálózat esetén hibát kapunk
        catch (Exception ex) {
            System.out.println(ex.getMessage());
            ResetHandler.reset();
        }
    }
}
